/**
 * tony
 * Apr 13, 2013
 */
package ttt.main;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

import ttt.components.StatusBar;

/**
 * 
 */
public class Main extends JFrame {

	int player = 1;
	String x = "X";
	String o = "O";
	boolean gameOver = false;
	private static final int UPPERLEFT = 0;
	private static final int UPPERMIDDLE = 1;
	private static final int UPPERRIGHT = 2;
	private static final int MIDDLELEFT = 3;
	private static final int MIDDLEMIDDLE = 4;
	private static final int MIDDLERIGHT = 5;
	private static final int LOWERLEFT = 6;
	private static final int LOWERMIDDLE = 7;
	private static final int LOWERRIGHT = 8;
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -770487875240669150L;
	private JPanel contentPane;
	private JLabel lblUpperLeft, lblUpperMiddle, lblUpperRight,
		lblMiddleLeft, lblMiddleMiddle, lblMiddleRight,
		lblLowerLeft, lblLowerMiddle, lblLowerRight;
	private StatusBar statusBar;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		} catch (Exception e) {
			System.out.println("Unable to load Windows look and feel");
		}
		
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Main frame = new Main();
					frame.setLocationRelativeTo(null);
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public Main() {
		setType(Type.POPUP);
		setTitle("TM TicTacToe");
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 372, 437);
		
		JMenuBar mainMenu = new JMenuBar();
		setJMenuBar(mainMenu);
		
		JMenu mnFile = new JMenu("File");
		mainMenu.add(mnFile);
		
		JMenuItem mntmNewGame = new JMenuItem("New Game");
		mntmNewGame.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				statusBar.addDraw();
				resetBoard();
			}
		});
		mnFile.add(mntmNewGame);
		
		JMenuItem mntmExit = new JMenuItem("Exit");
		mntmExit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				System.exit(0);
			}
		});
		mntmExit.setToolTipText("Exit");
		mnFile.add(mntmExit);
		
		JMenu mnAbout = new JMenu("About");
		mnAbout.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				JFrame aboutWindow = new About();
				aboutWindow.setLocationRelativeTo(contentPane);
				aboutWindow.setVisible(true);
//				 JFrame aWindow = new JFrame("This is the Window Title");
//				    int windowWidth = 400;           // Window width in pixels
//				    int windowHeight = 150;          // Window height in pixels
//				    aWindow.setBounds(50, 100,       // Set position
//				         windowWidth, windowHeight);  // and size
//				    aWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//				    aWindow.setVisible(true);        // Display the window
			}
		});

		mainMenu.add(mnAbout);
		contentPane = new JPanel();
		contentPane.setBackground(Color.GRAY);
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);

		lblUpperLeft = new JLabel("");
		lblUpperLeft.setBounds(45, 32, 93, 102);
		lblUpperLeft.setBorder(new LineBorder(new Color(0, 0, 0)));
		lblUpperLeft.setOpaque(true);
		lblUpperLeft.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				move(e);
			}
		});
		lblUpperLeft.setForeground(SystemColor.textText);
		lblUpperLeft.setBackground(Color.LIGHT_GRAY);
		lblUpperLeft.setHorizontalAlignment(SwingConstants.CENTER);
		lblUpperLeft.setFont(new Font("Tahoma", Font.PLAIN, 99));
		
		lblUpperMiddle = new JLabel("");
		lblUpperMiddle.setBounds(136, 32, 93, 102);
		lblUpperMiddle.setBorder(new LineBorder(new Color(0, 0, 0)));
		lblUpperMiddle.setOpaque(true);
		lblUpperMiddle.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				move(e);
			}
		});
		lblUpperMiddle.setBackground(Color.LIGHT_GRAY);
		lblUpperMiddle.setHorizontalAlignment(SwingConstants.CENTER);
		lblUpperMiddle.setFont(new Font("Tahoma", Font.PLAIN, 99));
		
		lblUpperRight = new JLabel("");
		lblUpperRight.setBounds(227, 32, 93, 102);
		lblUpperRight.setBorder(new LineBorder(new Color(0, 0, 0)));
		lblUpperRight.setOpaque(true);
		lblUpperRight.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				move(e);
			}
		});
		lblUpperRight.setBackground(Color.LIGHT_GRAY);
		lblUpperRight.setHorizontalAlignment(SwingConstants.CENTER);
		lblUpperRight.setFont(new Font("Tahoma", Font.PLAIN, 99));
		
		lblMiddleLeft = new JLabel("");
		lblMiddleLeft.setBounds(45, 132, 93, 102);
		lblMiddleLeft.setBorder(new LineBorder(new Color(0, 0, 0)));
		lblMiddleLeft.setOpaque(true);
		lblMiddleLeft.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				move(e);
			}
		});
		lblMiddleLeft.setBackground(Color.LIGHT_GRAY);
		lblMiddleLeft.setHorizontalAlignment(SwingConstants.CENTER);
		lblMiddleLeft.setFont(new Font("Tahoma", Font.PLAIN, 99));
		
		lblMiddleMiddle = new JLabel("");
		lblMiddleMiddle.setBounds(136, 132, 93, 102);
		lblMiddleMiddle.setBorder(new LineBorder(new Color(0, 0, 0)));
		lblMiddleMiddle.setOpaque(true);
		lblMiddleMiddle.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				move(e);
			}
		});
		lblMiddleMiddle.setBackground(Color.LIGHT_GRAY);
		lblMiddleMiddle.setHorizontalAlignment(SwingConstants.CENTER);
		lblMiddleMiddle.setFont(new Font("Tahoma", Font.PLAIN, 99));
		
		lblMiddleRight = new JLabel("");
		lblMiddleRight.setBounds(227, 132, 93, 102);
		lblMiddleRight.setBorder(new LineBorder(new Color(0, 0, 0)));
		lblMiddleRight.setOpaque(true);
		lblMiddleRight.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				move(e);
			}
		});
		lblMiddleRight.setBackground(Color.LIGHT_GRAY);
		lblMiddleRight.setHorizontalAlignment(SwingConstants.CENTER);
		lblMiddleRight.setFont(new Font("Tahoma", Font.PLAIN, 99));
		
		lblLowerRight = new JLabel("");
		lblLowerRight.setBounds(227, 233, 93, 102);
		lblLowerRight.setBorder(new LineBorder(new Color(0, 0, 0)));
		lblLowerRight.setOpaque(true);
		lblLowerRight.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				move(e);
			}
		});
		lblLowerRight.setBackground(Color.LIGHT_GRAY);
		lblLowerRight.setHorizontalAlignment(SwingConstants.CENTER);
		lblLowerRight.setFont(new Font("Tahoma", Font.PLAIN, 99));
		
		lblLowerLeft = new JLabel("");
		lblLowerLeft.setBounds(45, 233, 93, 102);
		lblLowerLeft.setBorder(new LineBorder(new Color(0, 0, 0)));
		lblLowerLeft.setOpaque(true);
		lblLowerLeft.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				move(e);
			}
		});
		contentPane.setLayout(null);
		
		lblLowerMiddle = new JLabel("");
		lblLowerMiddle.setBounds(136, 233, 93, 102);
		lblLowerMiddle.setBorder(new LineBorder(new Color(0, 0, 0)));
		lblLowerMiddle.setOpaque(true);
		lblLowerMiddle.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				move(e);
			}
		});
		lblLowerMiddle.setBackground(Color.LIGHT_GRAY);
		lblLowerMiddle.setHorizontalAlignment(SwingConstants.CENTER);
		lblLowerMiddle.setFont(new Font("Tahoma", Font.PLAIN, 99));
		contentPane.add(lblLowerMiddle);
		lblLowerLeft.setBackground(Color.LIGHT_GRAY);
		lblLowerLeft.setHorizontalAlignment(SwingConstants.CENTER);
		lblLowerLeft.setFont(new Font("Tahoma", Font.PLAIN, 99));
		contentPane.add(lblLowerLeft);
		contentPane.add(lblLowerRight);
		contentPane.add(lblUpperMiddle);
		contentPane.add(lblUpperLeft);
		contentPane.add(lblUpperRight);
		contentPane.add(lblMiddleMiddle);
		contentPane.add(lblMiddleLeft);
		contentPane.add(lblMiddleRight);
		
		int frameWidth = (int) getBounds().getWidth();
		int frameHeight = (int) getBounds().getHeight();
		statusBar = new StatusBar();
		statusBar.setBounds(0, frameHeight-70, frameWidth, 16);
		contentPane.add(statusBar);
	}
	
	private void move(MouseEvent arg0) {
		if (gameOver) {
			resetBoard();
			gameOver = false;
			return;
		}
		
		JLabel labelClicked = (JLabel) arg0.getComponent();
		if (!labelClicked.getText().equals("")) return;  //spot already played
		
		movePlayer1(labelClicked);
		
		if (checkWin(x)) {
			gameOver("You Won");
			statusBar.addWon();
			return;
		}
		if (checkFullBoard()) {
			gameOver("Draw");
			statusBar.addDraw();
			return;
		}
		
		movePlayer2();
		
		if (checkWin(o)) {
			gameOver("You Lost");
			statusBar.addLost();
			return;
		}
		if (checkFullBoard()) {
			gameOver("Draw");
			statusBar.addDraw();
			return;
		}
	}
	
	private void gameOver(String status) {
		JFrame gameOverDialog = new GameOver(status);
		gameOverDialog.setLocationRelativeTo(contentPane);
		gameOverDialog.setVisible(true);
		gameOver = true;
	}
	
	private void movePlayer1(JLabel labelClicked) {
		labelClicked.setText(x);

		player = 2;
	}
	
	private void movePlayer2() {
		moveComputer();
		
		player = 1;
	}
	
	private void moveComputer() {
		if (winComputerMove()) return;
		if (defendComputerMove()) return;
		randomComputerMove();
	}
	
	private boolean winComputerMove() {
		return computerMove(o);
	}
	
	private boolean defendComputerMove() {
		return computerMove(x);
	}
	
	private boolean computerMove(String playerToken) {
		// check left and middle
		if (lblUpperRight.getText().equals("") && lblUpperLeft.getText().equals(playerToken) && lblUpperMiddle.getText().equals(playerToken)) return moveComputer(UPPERRIGHT);
		if (lblMiddleRight.getText().equals("") && lblMiddleLeft.getText().equals(playerToken) && lblMiddleMiddle.getText().equals(playerToken)) return moveComputer(MIDDLERIGHT);
		if (lblLowerRight.getText().equals("") && lblLowerLeft.getText().equals(playerToken) && lblLowerMiddle.getText().equals(playerToken)) return moveComputer(LOWERRIGHT);
		
		// check left and right
		if (lblUpperMiddle.getText().equals("") && lblUpperLeft.getText().equals(playerToken) && lblUpperRight.getText().equals(playerToken)) return moveComputer(UPPERMIDDLE);
		if (lblMiddleMiddle.getText().equals("") && lblMiddleLeft.getText().equals(playerToken) && lblMiddleRight.getText().equals(playerToken)) return moveComputer(MIDDLEMIDDLE);
		if (lblLowerMiddle.getText().equals("") && lblLowerLeft.getText().equals(playerToken) && lblLowerRight.getText().equals(playerToken)) return moveComputer(LOWERMIDDLE);

		// check middle and right
		if (lblUpperLeft.getText().equals("") && lblUpperMiddle.getText().equals(playerToken) && lblUpperRight.getText().equals(playerToken)) return moveComputer(UPPERLEFT);
		if (lblMiddleLeft.getText().equals("") && lblMiddleMiddle.getText().equals(playerToken) && lblMiddleRight.getText().equals(playerToken)) return moveComputer(MIDDLELEFT);
		if (lblLowerLeft.getText().equals("") && lblLowerMiddle.getText().equals(playerToken) && lblLowerRight.getText().equals(playerToken)) return moveComputer(LOWERLEFT);
		
		// check upper and middle
		if (lblLowerLeft.getText().equals("") && lblUpperLeft.getText().equals(playerToken) && lblMiddleLeft.getText().equals(playerToken)) return moveComputer(LOWERLEFT);
		if (lblLowerMiddle.getText().equals("") && lblUpperMiddle.getText().equals(playerToken) && lblMiddleMiddle.getText().equals(playerToken)) return moveComputer(LOWERMIDDLE);
		if (lblLowerRight.getText().equals("") && lblUpperRight.getText().equals(playerToken) && lblMiddleRight.getText().equals(playerToken)) return moveComputer(LOWERRIGHT);
		
		// check upper and lower
		if (lblMiddleLeft.getText().equals("") && lblUpperLeft.getText().equals(playerToken) && lblLowerLeft.getText().equals(playerToken)) return moveComputer(MIDDLELEFT);
		if (lblMiddleMiddle.getText().equals("") && lblUpperMiddle.getText().equals(playerToken) && lblLowerMiddle.getText().equals(playerToken)) return moveComputer(MIDDLEMIDDLE);
		if (lblMiddleRight.getText().equals("") && lblUpperRight.getText().equals(playerToken) && lblLowerRight.getText().equals(playerToken)) return moveComputer(MIDDLERIGHT);
		
		// check middle and lower
		if (lblUpperLeft.getText().equals("") && lblMiddleLeft.getText().equals(playerToken) && lblLowerLeft.getText().equals(playerToken)) return moveComputer(UPPERLEFT);
		if (lblUpperMiddle.getText().equals("") && lblMiddleMiddle.getText().equals(playerToken) && lblLowerMiddle.getText().equals(playerToken)) return moveComputer(UPPERMIDDLE);
		if (lblUpperRight.getText().equals("") && lblMiddleRight.getText().equals(playerToken) && lblLowerRight.getText().equals(playerToken)) return moveComputer(UPPERRIGHT);

		// check diagonals
		if (lblLowerRight.getText().equals("") && lblUpperLeft.getText().equals(playerToken) && lblMiddleMiddle.getText().equals(playerToken)) return moveComputer(LOWERRIGHT);
		if (lblUpperRight.getText().equals("") && lblLowerLeft.getText().equals(playerToken) && lblMiddleMiddle.getText().equals(playerToken)) return moveComputer(UPPERRIGHT);
		if (lblLowerLeft.getText().equals("") && lblUpperRight.getText().equals(playerToken) && lblMiddleMiddle.getText().equals(playerToken)) return moveComputer(LOWERLEFT);
		if (lblUpperLeft.getText().equals("") && lblLowerRight.getText().equals(playerToken) && lblMiddleMiddle.getText().equals(playerToken)) return moveComputer(UPPERLEFT);
		if (lblMiddleMiddle.getText().equals("") && lblUpperLeft.getText().equals(playerToken) && lblLowerRight.getText().equals(playerToken)) return moveComputer(MIDDLEMIDDLE);
		if (lblMiddleMiddle.getText().equals("") && lblLowerLeft.getText().equals(playerToken) && lblUpperRight.getText().equals(playerToken)) return moveComputer(MIDDLEMIDDLE);
		
		return false;
	}
	
	private void randomComputerMove() {
		Random randomGenerator = new Random();
		int randomPick = randomGenerator.nextInt(9);
		while (!moveComputer(randomPick)) {
			randomPick = randomGenerator.nextInt(9);
		}
	}
	
	private boolean moveComputer(int computerPick) {
		switch (computerPick) {
			case 0: 
				if (lblUpperLeft.getText().equals("")) {
					lblUpperLeft.setText(o);
					return true;
				}
				break;
			case 1: 
				if (lblUpperMiddle.getText().equals("")) {
					lblUpperMiddle.setText(o);
					return true;
				}
				break;
			case 2: 
				if (lblUpperRight.getText().equals("")) {
					lblUpperRight.setText(o);
					return true;
				}
				break;
			case 3: 
				if (lblMiddleLeft.getText().equals("")) {
					lblMiddleLeft.setText(o);
					return true;
				}
				break;
			case 4: 
				if (lblMiddleMiddle.getText().equals("")) {
					lblMiddleMiddle.setText(o);
					return true;
				}
				break;
			case 5: 
				if (lblMiddleRight.getText().equals("")) {
					lblMiddleRight.setText(o);
					return true;
				}
				break;
			case 6: 
				if (lblLowerLeft.getText().equals("")) {
					lblLowerLeft.setText(o);
					return true;
				}
				break;
			case 7: 
				if (lblLowerMiddle.getText().equals("")) {
					lblLowerMiddle.setText(o);
					return true;
				}
				break;
			case 8: 
				if (lblLowerRight.getText().equals("")) {
					lblLowerRight.setText(o);
					return true;
				}
				break;
		}
		
		return false;
	}
	
	public boolean checkWin(String playerToken) {
		// check left to right
		if (lblUpperLeft.getText().equals(playerToken) && lblUpperMiddle.getText().equals(playerToken) && lblUpperRight.getText().equals(playerToken)) return true;
		if (lblMiddleLeft.getText().equals(playerToken) && lblMiddleMiddle.getText().equals(playerToken) && lblMiddleRight.getText().equals(playerToken)) return true;
		if (lblLowerLeft.getText().equals(playerToken) && lblLowerMiddle.getText().equals(playerToken) && lblLowerRight.getText().equals(playerToken)) return true;
		
		// check top to bottom
		if (lblUpperLeft.getText().equals(playerToken) && lblMiddleLeft.getText().equals(playerToken) && lblLowerLeft.getText().equals(playerToken)) return true;
		if (lblUpperMiddle.getText().equals(playerToken) && lblMiddleMiddle.getText().equals(playerToken) && lblLowerMiddle.getText().equals(playerToken)) return true;
		if (lblUpperRight.getText().equals(playerToken) && lblMiddleRight.getText().equals(playerToken) && lblLowerRight.getText().equals(playerToken)) return true;
		
		// check diagonal
		if (lblUpperLeft.getText().equals(playerToken) && lblMiddleMiddle.getText().equals(playerToken) && lblLowerRight.getText().equals(playerToken)) return true;
		if (lblLowerLeft.getText().equals(playerToken) && lblMiddleMiddle.getText().equals(playerToken) && lblUpperRight.getText().equals(playerToken)) return true;
		
		return false;
	}
	
	private void resetBoard() {
		lblUpperLeft.setText("");
		lblUpperMiddle.setText("");
		lblUpperRight.setText("");
		lblMiddleLeft.setText("");
		lblMiddleMiddle.setText("");
		lblMiddleRight.setText("");
		lblLowerLeft.setText("");
		lblLowerMiddle.setText("");
		lblLowerRight.setText("");
	}
	
	private boolean checkFullBoard() {
		if (!lblUpperLeft.getText().equals("") && !lblUpperMiddle.getText().equals("") && !lblUpperRight.getText().equals("")
				&& !lblMiddleLeft.getText().equals("") && !lblMiddleMiddle.getText().equals("") && !lblMiddleRight.getText().equals("")
				&& !lblLowerLeft.getText().equals("") && !lblLowerMiddle.getText().equals("") && !lblLowerRight.getText().equals("")) {
			return true;
		}
		
		return false;
	}
	
}